home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / rarp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-30  |  5.4 KB  |  220 lines

  1. /* Reverse Address Resolution Protocol (ARP) functions. Sits between IP and
  2.  * Level 2, mapping Level 2 addresses to IP.
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "proc.h"
  7. #include "timer.h"
  8. #include "iface.h"
  9. #include "socket.h"
  10. #include "ax25.h"
  11. #include "arp.h"
  12. #include "netuser.h"
  13. #include "cmdparse.h"
  14. #include "pktdrvr.h"
  15.  
  16. struct arp_stat Rarp_stat;
  17. static int Rwaiting = 0;    /* Semaphore used when waiting for a reply */
  18. static int dorarpquery __ARGS((int argc,char *argv[],void *p));
  19. static void rarpstat __ARGS((void));
  20. static void rarp_output __ARGS((struct iface *iface,int16 hardware,char *hwaddr,char *target));
  21.  
  22. static struct cmds Rarpcmds[] = {
  23.     "query", dorarpquery, 0, 3,
  24. #ifdef fixed
  25.     "rarp query <interface> <ether addr|callsign> [<ether addr|callsign>]",
  26. #else
  27.     "rarp query <interface> <callsign> [<callsign>]",
  28. #endif
  29.     NULLCHAR
  30. };
  31.  
  32. int
  33. dorarp(argc,argv,p)
  34. int argc;
  35. char *argv[];
  36. void *p;
  37. {
  38.     if(argc < 2){
  39.         rarpstat();
  40.         return 0;
  41.     }
  42.     return subcmd(Rarpcmds,argc,argv,p);
  43. }
  44.  
  45. static int
  46. dorarpquery(argc,argv,p)
  47. int argc;
  48. char *argv[];
  49. void *p;
  50. {
  51.     struct iface *ifp;
  52.     char hwaddr[MAXHWALEN], qhwaddr[MAXHWALEN];
  53.     int16 hardware, t;
  54.     static char *errmsg = "Illegal hardware address\n";
  55.     if((ifp = if_lookup(argv[1])) == NULLIF){
  56.          tprintf(Badinterface,argv[1]);
  57.          return -1;
  58.     }
  59.     switch(ifp->iftype->type) {
  60.     case CL_AX25:
  61.          hardware = ARP_AX25;
  62.          break;
  63. #ifdef fixed
  64.     case CL_ETHERNET:
  65.          hardware = ARP_ETHER;
  66.          break;
  67.     default:
  68.          tputs("Only Ethernet and AX25 interfaces allowed\n");
  69. #else
  70.     default:
  71.          tputs("Only AX25 interfaces allowed\n");
  72. #endif
  73.          return -1;
  74.     }
  75.     if((*ifp->iftype->scan)(hwaddr,argv[2]) == -1) {
  76.          tputs(errmsg);
  77.          return -1;
  78.     }
  79.     if(argc > 3 && (*ifp->iftype->scan)(qhwaddr,argv[3]) == -1) {
  80.          tputs(errmsg);
  81.          return -1;
  82.     }
  83.     if(argc == 3)
  84.          memcpy(qhwaddr,hwaddr,ifp->iftype->hwalen);
  85.     rarp_output(ifp,hardware,hwaddr,qhwaddr);
  86.  
  87.     t = Arp_type[hardware].pendtime;
  88.     ++Rwaiting;
  89.     tprintf("Trying...   %2d",t);
  90.     while(t--) {
  91.          alarm(1000L);
  92.          if(pwait(&Rwaiting) != EALARM) {
  93.           alarm(0);
  94.           --Rwaiting;
  95.           return 0;
  96.          }
  97.          tprintf("\b\b%2d",t);
  98.     }
  99.     tputs("\b\bTimeout.\n");
  100.     --Rwaiting;
  101.     return 0;
  102. }
  103.  
  104. /* Handle incoming RARP packets according to RFC 903.
  105.  */
  106. void
  107. rarp_input(iface,bp)
  108. struct iface *iface;
  109. struct mbuf *bp;
  110. {
  111.     struct arp rarp;
  112.     struct arp_type *at;
  113.     char shwaddr[MAXHWALEN];
  114.     
  115.     Rarp_stat.recv++;
  116.     if(ntoharp(&rarp,&bp) == -1)    /* Convert into host format */
  117.         return;
  118.     if(rarp.hardware >= NHWTYPES){
  119.         /* Unknown hardware type, ignore */
  120.         Rarp_stat.badtype++;
  121.         return;
  122.     }
  123.     at = &Arp_type[rarp.hardware];
  124.     if(rarp.protocol != at->iptype){
  125.         /* Unsupported protocol type, ignore */
  126.         Rarp_stat.badtype++;
  127.         return;
  128.     }
  129.     if(uchar(rarp.hwalen) > MAXHWALEN || uchar(rarp.pralen) != sizeof(int32)){
  130.         /* Incorrect protocol addr length (different hw addr lengths
  131.          * are OK since AX.25 addresses can be of variable length)
  132.          */
  133.         Rarp_stat.badlen++;
  134.         return;
  135.     }
  136.     if(memcmp(rarp.shwaddr,at->bdcst,at->hwalen) == 0){
  137.         /* This guy is trying to say he's got the broadcast address! */
  138.         Rarp_stat.badaddr++;
  139.         return;
  140.     }
  141.     if(rarp.opcode == REVARP_REQUEST) {
  142.         /* We are not a server, so we can only answer requests for a
  143.          * hardware address that is our own. But would be possible to
  144.          * use the ARP table to answer requests for someone elses
  145.          * IP address.
  146.          */
  147.         if(memcmp(rarp.thwaddr,iface->hwaddr,at->hwalen) == 0) {
  148.             memcpy(shwaddr,rarp.shwaddr,at->hwalen);
  149.             /* Mark the end of the sender's AX.25 address
  150.              * in case he didn't
  151.              */
  152.             if(rarp.hardware == ARP_AX25)
  153.                 rarp.thwaddr[uchar(rarp.hwalen)-1] |= E;
  154.             memcpy(rarp.shwaddr,iface->hwaddr,at->hwalen);
  155.             rarp.sprotaddr = iface->addr;
  156.             rarp.tprotaddr = iface->addr;
  157.             rarp.opcode = REVARP_REPLY;
  158.  
  159.             if((bp = htonarp(&rarp)) == NULLBUF)
  160.                 return;
  161.  
  162.             if(iface->forw != NULLIF)
  163.                  (*iface->forw->output)(iface->forw,shwaddr,
  164.                     iface->forw->hwaddr,at->rarptype,bp);
  165.             else
  166.                  (*iface->output)(iface,shwaddr,
  167.                     iface->hwaddr,at->rarptype,bp);
  168.             Rarp_stat.inreq++;
  169.         }
  170.     } else {
  171.         Rarp_stat.replies++;
  172.         if(Rwaiting) {
  173.              psignal(&Rwaiting,1);
  174.              tprintf("\nRARP Reply: %s %s\n",
  175.                  (*at->format)(shwaddr,rarp.thwaddr),
  176.                  inet_ntoa(rarp.tprotaddr));
  177.         }
  178.     }
  179. }
  180.  
  181. /* Send a RARP request to target to resolve hardware address hwaddr */
  182. static void
  183. rarp_output(iface,hardware,hwaddr,target)
  184. struct iface *iface;
  185. int16 hardware;
  186. char *hwaddr;
  187. char *target;
  188. {
  189.     struct arp rarp;
  190.     struct mbuf *bp;
  191.     struct arp_type *at;
  192.  
  193.     at = &Arp_type[hardware];
  194.     if(iface->output == NULLFP)
  195.         return;
  196.     
  197.     rarp.hardware = hardware;
  198.     rarp.protocol = at->iptype;
  199.     rarp.hwalen = at->hwalen;
  200.     rarp.pralen = sizeof(int32);
  201.     rarp.opcode = REVARP_REQUEST;
  202.     memcpy(rarp.shwaddr,iface->hwaddr,at->hwalen);
  203.     rarp.sprotaddr = 0;
  204.     memcpy(rarp.thwaddr,hwaddr,at->hwalen);
  205.     rarp.tprotaddr = 0;
  206.     if((bp = htonarp(&rarp)) == NULLBUF)
  207.         return;
  208.     (*iface->output)(iface,target,
  209.         iface->hwaddr,at->rarptype,bp);
  210.     Rarp_stat.outreq++;
  211. }
  212.  
  213. static void
  214. rarpstat()
  215. {
  216.     tprintf("received %u badtype %u bogus addr %u reqst in %u replies %u reqst out %u\n",
  217.      Rarp_stat.recv,Rarp_stat.badtype,Rarp_stat.badaddr,Rarp_stat.inreq,
  218.      Rarp_stat.replies,Rarp_stat.outreq);
  219. }
  220.